<?php
/* Yahoo! Weather API component for Cakephp
 * @author Arash Hemmat www.hemmat.biz
 * @version 1.2  some bugs has been fixed.
 * @license http://www.opensource.org/licenses/mit-license.php
 * Special thanks to "Ed Eliot" (http://www.ejeliot.com/blog/38) ,I used his code for this component.
 */

/*
 * Yahoo weather component class
 */
class WeatherComponent extends Object
{
    /*
     * @var bool
     */
    var $controller = true;

    /*
     * @var array
     */
    var $errors=array();

    /*
     * @var string
     */
    var $content;

    /*
     * The url of Yahoo! weather API
     * @var string
     */
    var $_api_url='http://weather.yahooapis.com/forecastrss';

    /*
     * THe address for images, you need to change this if you want to use your own images.
     * @var string
     */
    var $_image_base='http://l.yimg.com/a/i/us/nws/weather/gr/';
    var $_forecast_image_base = 'http://l.yimg.com/us.yimg.com/i/us/we/52/';

    /*
     * initialization
     * @param bool $controller
     */
    function startup(&$controller)
    {
        $this->controller =& $controller;
    }

    /*
     * Get the weather information for given location code
     * @param string $locationCode a code that represent a location in Yahoo weather system
     * @param string $degreeUnit it could be f: Fahrenheit or c: Celsius
     * @param bool $translate this parametr indicates if the result should be translated of not
     * @return array|bool $result
     */
    public function get_weather(){
        // Set log name
        $log = 'weather';
        // Set our cache for 1 hour
        Cache::set(array('duration' => '+4 hours'));
        // Check if we have anything already cached
        $city = Configure::read('Weather.city');
        $unit = Configure::read('Weather.unit');
        $cache = 'weather.' . $city;
        $weather = Cache::read($cache);
        // If we do, then read it into $this->content
        // If we don't, fetch it from Yahoo, put it into $this->data, and then cache it
        if($weather !== false){
            $this->content = unserialize(Cache::read($cache));
            $this->log('Read from local file cache', $log);
        }else{
            $this->log('Reqeust from yahoo weather server ', $log);
            App::import('Core', 'HttpSocket');
            $HttpSocket = new HttpSocket();
            $this->content = $HttpSocket->get($this->_api_url, 'w='.$city.'&u='.$unit);
            if(!empty($this->content)){
                Cache::write($cache, serialize($this->content));
            }
        }
        if(!empty($this->content)){
            $result['location']=$this->_get_attributes('yweather:location');
            $result['condition']=$this->_get_attributes('yweather:condition');
            $result['units']=$this->_get_attributes('yweather:units');
            $result['wind']=$this->_get_attributes('yweather:wind');
            $result['atmosphere']=$this->_get_attributes('yweather:atmosphere');
            $result['astronomy']=$this->_get_attributes('yweather:astronomy');
            $result['geo:lat']=$this->_get_value('geo:lat');
            $result['geo:long']=$this->_get_value('geo:long');
            $result['link']=explode('*',$this->_get_value('link'));
            $result['pubDate']=$this->_get_value('pubDate');
            $result['description']=$this->_get_value('description');
            $result['image']=$this->_image_base.$result['condition']['code'].'n.png';
            $forecasts=$this->_get_attributes('yweather:forecast');
            $result['tonight']=$forecasts[0];
            $result['tonight']['image']=$this->_forecast_image_base.$result['tonight']['code'].'.gif';
            $result['tomorrow']=$forecasts[1];
            $result['tomorrow']['image']=$this->_forecast_image_base.$result['tomorrow']['code'].'.gif';
            return $result;
        }else{
            return false;
        }
    }

    /*
     * @param string $sTag
     * @return bool
     */
    private function _get_value($sTag){
        $aMatches = array();
        if (preg_match("/<$sTag>([^<]*)<\/$sTag>/i", $this->content, $aMatches)){
            $aResult = array();
            $aResult['value'] = $aMatches[1];
            return trim($aMatches[1]);
        }
        return false;
    }

    /*
     * @param string $sTag
     * @return string $aResult
     */
    private function _get_attributes($sTag){
        $aMatches = array();
        /* Initial Regx for attributes::/<$sTag([^\/]*)\/>/i */
        if (preg_match_all("/<$sTag(.*)\/>/i", $this->content, $aMatches)){
            $aResult = array();
            for ($i = 0; $i < count($aMatches[1]); $i++){
                $aSubMatches = array();
                if (preg_match_all("/([^=]+)=\"([^\"]*)\"/i", $aMatches[1][$i], $aSubMatches)){
                    for ($j = 0; $j < count($aSubMatches[1]); $j++){
                        $aResult[$i][trim($aSubMatches[1][$j])] = trim($aSubMatches[2][$j]);
                    }
                }
            }
            $iNumResults = count($aResult);
            if ($iNumResults > 1){
                return $aResult;
            }elseif($iNumResults == 1){
                return $aResult[0];
            }
        }
        return false;
    }
}
?>
